package com.atlin.project.service.impl;

import cn.hutool.json.JSONUtil;
import com.atlin.beaconsapiclientsdk.client.BeaconsApiClient;
import com.atlin.beaconsapiclientsdk.common.ClientInvokeRequest;
import com.atlin.beaconsapicommon.model.domain.SysUser;
import com.atlin.beaconsapicommon.model.domain.interfaceInfo.InterfaceInfo;
import com.atlin.beaconsapicommon.model.domain.interfaceInfo.InvokeRequestField;
import com.atlin.beaconsapicommon.model.domain.interfaceInfo.UserInterfaceInfo;
import com.atlin.project.common.ErrorCode;
import com.atlin.project.contant.CommonConstant;
import com.atlin.project.exception.BusinessException;
import com.atlin.project.exception.ThrowUtils;
import com.atlin.project.mapper.InterfaceInfoMapper;
import com.atlin.project.mapper.UserInterfaceInfoMapper;
import com.atlin.project.model.dto.interfaceInfo.InterfaceInfoQueryRequest;
import com.atlin.project.model.vo.InterfaceInfoVO;
import com.atlin.project.service.InterfaceInfoService;
import com.atlin.project.utils.sql.SqlUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author atlin
 * @description interfaceInfo
 * @createDate date
 */
@Slf4j
@Service
public class InterfaceInfoServiceImpl extends ServiceImpl<InterfaceInfoMapper, InterfaceInfo>
        implements InterfaceInfoService {

    @Resource
    private BeaconsApiClient beaconsApiClient;

    @Resource
    private UserInterfaceInfoMapper userInterfaceInfoMapper;

    @Override
    @Transactional
    public int totalInvokeCount() {
        // 分组查询计算每个接口的总调用次数
        List<UserInterfaceInfo> userInterfaceInfoList = userInterfaceInfoMapper.totalInvokeCount();
        List<InterfaceInfo> updateList = new ArrayList<>(userInterfaceInfoList.size());
        
        for (UserInterfaceInfo userInterfaceInfo : userInterfaceInfoList) {
            Long interfaceInfoId = userInterfaceInfo.getInterfaceInfoId();
            Integer totalNum = userInterfaceInfo.getTotalNum();

            InterfaceInfo interfaceInfo = new InterfaceInfo();
            interfaceInfo.setId(interfaceInfoId);
            interfaceInfo.setTotalInvoke(Long.valueOf(totalNum));

            updateList.add(interfaceInfo);
        }

        boolean b = this.updateBatchById(updateList);
        return b ? updateList.size() : 0;
    }

    @Override
    public void valid(InterfaceInfo interfaceInfo, boolean add) {

    }

    @Override
    public InterfaceInfoVO getInterfaceInfoVO(InterfaceInfo interfaceInfo, HttpServletRequest request) {
        return InterfaceInfoVO.objToVo(interfaceInfo);
    }

    /**
     * 获取查询包装类（用户根据哪些字段查询，根据前端传来的请求对象，得到 mybatis 框架支持的查询 QueryWrapper 类）
     *
     * @param interfaceInfoQueryRequest
     * @return
     */
    @Override
    public QueryWrapper<InterfaceInfo> getQueryWrapper(InterfaceInfoQueryRequest interfaceInfoQueryRequest) {
        QueryWrapper<InterfaceInfo> queryWrapper = new QueryWrapper<>();
        if (interfaceInfoQueryRequest == null) {
            return queryWrapper;
        }
        Long id = interfaceInfoQueryRequest.getId();
        String sortField = interfaceInfoQueryRequest.getSortField();
        String sortOrder = interfaceInfoQueryRequest.getSortOrder();
        String searchText = interfaceInfoQueryRequest.getSearchText();
        String name = interfaceInfoQueryRequest.getName();
        String description = interfaceInfoQueryRequest.getDescription();
        String host = interfaceInfoQueryRequest.getHost();
        String url = interfaceInfoQueryRequest.getUrl();
        String method = interfaceInfoQueryRequest.getMethod();
        Integer status = interfaceInfoQueryRequest.getStatus();
        Long userId = interfaceInfoQueryRequest.getUserId();


        queryWrapper.like(StringUtils.isNotBlank(name), "name", name);
        queryWrapper.like(StringUtils.isNotBlank(description), "description", description);
        queryWrapper.like(StringUtils.isNotBlank(host), "host", host);
        queryWrapper.like(StringUtils.isNotBlank(url), "url", url);
        queryWrapper.eq(ObjectUtils.isNotEmpty(method), "method", method);
        queryWrapper.eq(ObjectUtils.isNotEmpty(id), "id", id);
        queryWrapper.eq(ObjectUtils.isNotEmpty(status), "status", status);
        queryWrapper.eq(ObjectUtils.isNotEmpty(userId), "userId", userId);
        queryWrapper.eq("isDelete", false);
        queryWrapper.orderBy(SqlUtils.validSortField(sortField),
                sortOrder.equals(CommonConstant.SORT_ORDER_ASC), sortField);

        return queryWrapper;
    }

    @Override
    public Page<InterfaceInfoVO> getInterfaceInfoVOPage(Page<InterfaceInfo> interfaceInfoPage, HttpServletRequest request) {
        List<InterfaceInfo> interfaceInfoList = interfaceInfoPage.getRecords();
        Page<InterfaceInfoVO> interfaceInfoVOPage = new Page<>(interfaceInfoPage.getCurrent(), interfaceInfoPage.getSize(), interfaceInfoPage.getTotal());
        if (CollectionUtils.isEmpty(interfaceInfoList)) {
            return interfaceInfoVOPage;
        }

        // 填充信息
        List<InterfaceInfoVO> interfaceInfoVOList = interfaceInfoList.stream().map(InterfaceInfoVO::objToVo).collect(Collectors.toList());
        interfaceInfoVOPage.setRecords(interfaceInfoVOList);
        return interfaceInfoVOPage;
    }

    @Override
    public Object testInterfaceInvoke(long interfaceInfoId, List<InvokeRequestField> paramList) {
        InterfaceInfo interfaceInfo = getById(interfaceInfoId);

        ThrowUtils.throwIf(interfaceInfo == null, ErrorCode.NULL_ERROR, "接口不存在");

        // 校验接口是否能使用
        String url = interfaceInfo.getUrl();
        String host = interfaceInfo.getHost();
        String requestParamsExampleFields = interfaceInfo.getRequestParamsExample();

        String methodName = StringUtils.substringAfterLast(url, "/");
        try {

            // 如果paramList为空，则尝试使用示例参数
            if (paramList == null || paramList.isEmpty()) {
                if (StringUtils.isNotBlank(requestParamsExampleFields)) {
                    paramList = JSONUtil.toList(requestParamsExampleFields, InvokeRequestField.class);
                }
            }

            // 获取方法对象和参数
            Class<?>[] parameterTypes = getParameterTypes(paramList);
            Method method = beaconsApiClient.getClass().getMethod(methodName, parameterTypes);
            Object[] argsArray = getArgsArray(paramList);

            // 调用方法并传入参数
            Object res = method.invoke(beaconsApiClient, argsArray);
            ThrowUtils.throwIf(res == null, ErrorCode.SYSTEM_ERROR, "接口服务异常");
            return res;
        } catch (IllegalArgumentException e) {
            log.error("xxx 参数转换异常 {}{}", host, url, e);
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数类型错误");
        } catch (NoSuchMethodException e) {
            log.error("xxx 接口不存在 {}{}", host, url, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "接口不存在");
        } catch (Exception e) {
            log.error("xxx 接口测试调用失败 {}{}\n", host, url, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "接口服务调用失败，请稍后再试");
        }
    }

    @Override
    public Object remoteInterfaceInvoke(SysUser loginUser, long interfaceInfoId, List<InvokeRequestField> paramList) {
        InterfaceInfo interfaceInfo = getById(interfaceInfoId);
        ThrowUtils.throwIf(interfaceInfo == null, ErrorCode.NULL_ERROR, "接口不存在");
        ThrowUtils.throwIf(loginUser == null, ErrorCode.NOT_LOGIN, "接口不存在");

        String host = interfaceInfo.getHost();
        String url = interfaceInfo.getUrl();
        String method = interfaceInfo.getMethod();
        ClientInvokeRequest invokeRequest = new ClientInvokeRequest();
        invokeRequest.setHost(host);
        invokeRequest.setUrl(url);
        invokeRequest.setMethodType(method);
        HashMap<String, Object> map = new HashMap<>();
        // 构建请求参数
        try {
            if (paramList != null && !paramList.isEmpty()) {
                for (InvokeRequestField invokeRequestField : paramList) {
                    map.put(invokeRequestField.getFieldName(), argsTypeConvertCheck(invokeRequestField));
                }
            }
        } catch (IllegalArgumentException e) {
            log.error("xxx 参数转换异常 {}{}", host, url, e);
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "参数类型错误");
        }
        invokeRequest.setParams(map);

        // 使用用户调用客户端
        String accessKey = loginUser.getAccessKey();
        String secretKey = loginUser.getSecretKey();
        BeaconsApiClient tempBeaconsApiClient = new BeaconsApiClient(accessKey, secretKey);

        return tempBeaconsApiClient.invoke(invokeRequest);
    }

    // 根据参数数据获取参数类型的Class数组
    private static Class<?>[] getParameterTypes(List<InvokeRequestField> parameters) {
        if (parameters == null || parameters.isEmpty()) return new Class[]{};
        return parameters.stream()
                .map(param -> {
                    switch (param.getType()) {
                        case "String":
                            return String.class;
                        case "Integer":
                            return Integer.class;
                        case "Long":
                            return Long.class;
                        case "Boolean":
                            return Boolean.class;
                        case "Double":
                            return Double.class;
                        // 添加其他类型的处理
                        default:
                            throw new IllegalArgumentException("Unsupported type: " + param.getType());
                    }
                })
                .toArray(Class<?>[]::new);
    }

    // 根据参数数据获取参数值的数组
    private static Object[] getArgsArray(List<InvokeRequestField> parameters) {
        if (parameters == null || parameters.isEmpty()) return new Object[]{};
        return parameters.stream()
                .map(InterfaceInfoServiceImpl::argsTypeConvertCheck)
                .toArray();
    }

    // 根据参数数据获取参数值 
    private static Object argsTypeConvertCheck(InvokeRequestField invokeRequestField) {
        if (invokeRequestField == null) return null;
        switch (invokeRequestField.getType()) {
            case "String":
                return invokeRequestField.getValue();
            case "Integer":
                return Integer.parseInt(invokeRequestField.getValue());
            case "Long":
                return Long.parseLong(invokeRequestField.getValue());
            case "Boolean":
                return Boolean.parseBoolean(invokeRequestField.getValue());
            case "Double":
                return Double.parseDouble(invokeRequestField.getValue());
            // 添加其他类型的处理
            default:
                throw new IllegalArgumentException("Unsupported type: " + invokeRequestField.getType());
        }
    }
}




